#include "sysconfig.h"
#include "execlib.h"
#include "consolehook.h"
#include "options.h"
#include "rommgr.h"
#include "uae.h"
#include "thread.h"
#include "newcpu.h"
#include "traps.h"
#include "disk.h"
#include "keybuf.h"

static uae_ptr beginio;

void consolehook_config(CConfiguration* p)
{
    int roms[] = { 15, 31, 16, 46, -1 };

    default_prefs(p);
    // p->headless = 1;
    p->sound_produce = false;
    p->gfx_resolution = 0;
    p->gfx_vresolution = 0;
    p->gfx_scanlines = false;
    p->gfx_framerate = 10;
    p->immediate_blits = 1;
    p->collision_level = 0;
    configure_rom(p, roms, 0);
    p->cpu_model = 68020;
    p->fpu_model = 68882;
    p->m68k_speed = -1;
    p->jit_cache_size = 8192;
    p->cpu_compatible = 0;
    p->address_space_24 = 0;
    p->chipmem_size = 0x00200000;
    p->fastmem_size = 0x00800000;
    p->slowmem_size = 0;
    p->setfloppycount(1);
    // p->floppies[1].dfxtype = DRV_NONE;
    p->floppy_speed = 0;
    // p->start_gui = 0;
    p->gfx_size_win.width = 320;
    p->gfx_size_win.height = 256;
    p->turbo_emulation = 0;
    // p->win32_automount_drives = 2;
    // p->win32_automount_cddrives = 2;

    add_filesys_config(p, -1, L"DH0", L"CLIBOOT", L".", 1, 0, 0, 0, 0, 15, nullptr, 0);
}

static void* console_thread(void* v)
{
    uae_set_thread_priority(nullptr, 1);
    for (;;)
    {
        TCHAR wc = Logger::ConsoleGetChar();
        char c[2];

        Logger::Write(L"*");
        c[0] = 0;
        c[1] = 0;
        Unicode::ua_copy(c, 1, &wc);
        record_key_direct((0x10 << 1) | 0);
        record_key_direct((0x10 << 1) | 1);
    }
}

int consolehook_activate()
{
    return console_emulation;
}

void consolehook_ret(uae_ptr condev, uae_ptr oldbeginio)
{
    beginio = oldbeginio;

    if (Logging::CONSOLE_HOOK_DEBUG)
        Logger::Write(L"console.device at %08X\n", condev);

    uae_start_thread(L"consolereader", console_thread, nullptr, nullptr);
}

uae_ptr consolehook_beginio(uae_ptr request)
{
    uint io_data = get_long(request + 40);  // 0x28
    uint io_length = get_long(request + 36);  // 0x24
    uint io_actual = get_long(request + 32);  // 0x20
    uint io_offset = get_long(request + 44);  // 0x2c
    ushort cmd = get_word(request + 28);

    if (cmd == CMD_WRITE)
    {
        TCHAR* buf;
        const char* src = (char*)get_real_address(io_data);
        int len = io_length;
        if (io_length == -1)
            len = strlen(src);
        buf = xmalloc(TCHAR, len + 1);
        Unicode::au_copy(buf, len, src);
        buf[len] = 0;
        Logger::FileOut(L"%s", buf);
        free(buf);
    }
    else if (cmd == CMD_READ)
    {
        if (Logging::CONSOLE_HOOK_DEBUG)
            Logger::Write(L"%08x: CMD=%d LEN=%d OFF=%d ACT=%d\n", request, cmd, io_length, io_offset, io_actual);
    }

    return beginio;
}